

package protocols.joinProtocol;

import peer.Connection;
import peer.Message;
import peer.Peer;
import protocols.Protocol;
import protocols.ProtocolState;

public class JoinProtocol<T extends Enum<?>, S extends Enum<?>> extends Protocol<T,S> {
	public static final String NAME = "JoinProtocol";
		public String getName() { return NAME; }
	
	public enum MessageTypes {join, address, leader}; 
	public enum States {leader, joining};
	
	
	protected JoinProtocol() {
		super();
	}
	
	@SuppressWarnings("unchecked")
	protected JoinProtocol(Connection _conn) {
		super(_conn);
		
		addHandler((S)States.leader, new LeaderState());
		addHandler((S)States.joining, new JoiningState());
	}
	
	/**
	 * Takes a connection to be monitored as an argument.  Initializes a new instance of JoinProtocol on the provided connection and starts it returning a reference to the newly running protocol.
	 * 
	 * @param conn Connection to be monitored
	 * @return new running instance of JoinProtocol
	 */
	public static JoinProtocol monitor(Connection conn) {
		JoinProtocol<MessageTypes,States> p = new JoinProtocol<MessageTypes,States>(conn);
		conn.registerProtocol(NAME, p);
		p.setState(States.joining);
		new Thread(p, "JoinProtocol").start();
		
		return p;		
		
	}
	
	private class LeaderState  extends ProtocolState<S> {
		
	
		@Override
		public void handle(Message packet, Connection conn) {
			System.out.println("\t"+getState()+": "+packet);	
			if (MessageTypes.valueOf(packet.type) == MessageTypes.join) {
				System.out.println("\tjoin request recieved, replying...");	
				
//				packet.id = (String)packet.data;
//				packet.type = MessageTypes.address.toString();
//				packet.data = "80";
//				conn.write((Message<String>)packet);
				callback.addPeer(((Message<String>)packet).data);
				
			}
		}
		
	}
	
	private class JoiningState extends ProtocolState {

		@Override
		public void handle(Message packet, Connection conn) {
			
			System.out.println("reply to join recieved: ");
			System.out.println("\t" + packet.type);
			if (MessageTypes.valueOf(packet.type) == MessageTypes.address) {
				System.out.println("Target port: " + ((Message<String>)packet).data);
			}
		}
		
	}


	

}
